package demo8;


// 线程安全
public class Test15 {
    public static int count =0;
    public static void main01(String[] args) throws InterruptedException {

        // 当我们这里进行两个线程同时操作一个数据的时候，就可能会出现bug：
        // 由于count++ 在cpu中执行不是原子性的，就可能导致，两线程在操作的时候，一线程还没来得及将结果存进内存，另一个线程就开始读取了
        //此时就会导致，第一个线程操作一次，第二个线程操作一次，总计2次，但是由于上述bug，导致可能就只操作一次
        Thread t1=new Thread(()->{
            for(int i=0;i<50000;i++){
                count++;
            }
        });
        Thread t2=new Thread(()->{
            for(int i=0;i<50000;i++){
                count++;
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        // 当然，如果两线程中操作的次数不是很多，由于cpu核心处理数据的速度特别快，另外一个线程还没操作，第一个线程就已经操作完成了，所以就不会出现bug
        System.out.println("count : "+count);
    }


    public static void main(String[] args) throws InterruptedException {
        // 为了防止出现上面的bug ，我们就可以从下面三个方面来进行调整
        //1. 操作系统对线程的调度是随机的，由于计算机核心是采用的 抢占式 运行    --- 》 这里Java已经规定好了，不好修改
        //2. 两线程操作同一个数据               --- 》 这里是我们的需求
        //3. 执行的操作对cpu来讲不是原子的
        // 只有第三种我们可以进行干预，那么如何将操作变成原子的呢： 我们可以对操作进行加锁

        Object object=new Object();
        Object object2=new Object();
        Thread t1=new Thread(()->{
            for(int i=0;i<50000;i++){
                // 当我们对操作进行加锁的时候，其他线程如果要访问相同的数据，就必须等锁解开才能继续访问
                // 当然你也要对同一个对象加锁，不然还是会出现bug
                synchronized(object){
                    count++;
                }
            }
        });
        Thread t2=new Thread(()->{
            for(int i=0;i<50000;i++){
                synchronized(object){
                    count++;
                }
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("count : "+count);
    }
}
